package com.erdos.core.service.impl;

import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.erdos.core.constant.ReferenceConstant;
import com.erdos.core.entity.ContentText;
import com.erdos.core.entity.FieldDefinition;
import com.erdos.core.entity.FieldVO;
import com.erdos.core.entity.RefTableDetail;
import com.erdos.core.service.ContentTextService;
import com.erdos.core.service.FieldDefinitionService;
import com.erdos.core.service.RefTableDetailService;
import com.erdos.core.service.ReferenceService;
public class ReferenceServiceImpl implements ReferenceService {

	private static final Log logger =
		LogFactory.getLog(ReferenceServiceImpl.class);
	private RefTableDetailService refTableDetailService =null;
	private FieldDefinitionService fieldDefinitionService = null;
	private ContentTextService contentTextService = null;
	
	/**
	 * 用于验证value是否符合Field的定义
	 * @param fieldSid
	 * @param value
	 * @return String   true:0:0:0     false:类型:长度:精度  false:0:0:0 (field不存在)
	 * @author xuzhang4
	 * @since  2008-7-27
	 */
	public String checkValue(Long fieldSid, String value) {
		if (fieldSid == null) {
			String str = "Illegal null fieldSid.";
			logger.warn(str);
			throw new IllegalArgumentException(str);
		}
		if (value == null) {
			String str = "Illegal null value string.";
			logger.warn(str);
			throw new IllegalArgumentException(str);
		}
		FieldDefinition fieldDef =
			this.fieldDefinitionService.findByPrimaryKey(fieldSid);
		if (fieldDef == null) {
			String str = "Specified fieldSid not exist.";
			logger.warn(str);
			return "false:0:0:0" ;
		}
		if (fieldDef.getDecimalLength() == null) {
			fieldDef.setDecimalLength(0L);
		}
		String dbType = fieldDef.getDataTypeDb();
		if (dbType.equals("DATE")) {
			try {
				java.sql.Date.valueOf(value) ;
				return "true:0:0:0";
			} catch (Exception e) {
				try{
					Timestamp.valueOf(value);
					return "true:0:0:0";
				}catch(Exception ex){
					return "false:DATE:0:0";
				}
			}
		} else if (dbType.equals("NUMBER")) {
			try {
				if (fieldDef.getDecimalLength() > 0) {
					int dotIndex = value.indexOf(".");
					if (dotIndex >= 0) {
						String intPart = value.substring(0, dotIndex);
						String decimalPart = value.substring(dotIndex + 1);
						Long.parseLong(intPart);
						Long.parseLong(decimalPart);
						if (intPart.length()
								> (fieldDef.getLen() - fieldDef.getDecimalLength())) {
							throw new Exception();
						}
						if (decimalPart.length() > fieldDef.getDecimalLength()) {
							throw new Exception();
						}
					} else {
						Long.parseLong(value);
						if (value.length()
								> (fieldDef.getLen() - fieldDef.getDecimalLength())) {
							throw new Exception();
						}
					}
					return "true:0:0:0"; 
				} else {
					Long.parseLong(value);
					if (value.length() > fieldDef.getLen()) {
						throw new Exception();
					}
					return "true:0:0:0";
				}
			} catch (Exception e) {
				return "false:" + fieldDef.getDataTypeDb() + ":"
				+ fieldDef.getLen() + ":" + fieldDef.getDecimalLength();
			}
		} else {
			//进行中文字符的转换  默认为UTF-8编码  需转换
			byte[] parseString = null ;
			try {
					parseString = value.getBytes("utf-8") ;
			} catch (UnsupportedEncodingException ex) {
				return "false:" + fieldDef.getDataTypeDb() + ":"
				+ fieldDef.getLen() + ":" + fieldDef.getDecimalLength();
			}
			
			if (parseString.length > fieldDef.getLen()) {
				return "false:" + fieldDef.getDataTypeDb() + ":"
				+ fieldDef.getLen() + ":" + fieldDef.getDecimalLength();
			}
			return "true:0:0:0";
		}
	}

	/**
	 * 用于查找fieldSid对应语言的ContentText
	 * @param fieldId
	 * @param locale
	 * @return FieldVO
	 * @author xuzhang4
	 * @since  2008-7-27
	 */
	public FieldVO findFieldContent(Long fieldSid, Locale locale) {
		if (fieldSid == null) {
			String str = "Illegal null fieldSid.";
			logger.warn(str);
			throw new IllegalArgumentException(str);
		}
		
        if (locale == null) {
            locale = new Locale("zh", "CN");
        }
//		if (locale == null) {
//			String str = "Illegal null locale.";
//			logger.warn(str);
//			throw new IllegalArgumentException(str);
//		}
		FieldDefinition fieldDef =
			this.fieldDefinitionService.findByPrimaryKey(fieldSid);
		if (fieldDef == null) {
			return null;
		}
		FieldVO fieldVO = new FieldVO();
		fieldVO.setFieldSid(fieldDef.getSid());
		fieldVO.setFieldId(fieldDef.getFieldId());
		fieldVO.setDataType(fieldDef.getDataType());
		fieldVO.setUnitOfMeasure(fieldDef.getUnitOfMeasure());
		
		String contentId = fieldDef.getContentId();
		Map<String, Object> detailParams = new HashMap<String, Object>();
		detailParams.put("refTableId", ReferenceConstant.REFERENCE_LANGUAGE);
		detailParams.put("key1Value", locale.toString());
		RefTableDetail refTableDetail =
			this.refTableDetailService.findUniqueByParams(detailParams);
		if (refTableDetail == null) {
			detailParams.put("key1Value", "en_US");
			refTableDetail =
				this.refTableDetailService.findUniqueByParams(detailParams);
			if (refTableDetail == null) {
				return fieldVO;
			}
			String str = "Can not find specified locale in $LANGUAGE, use en_US as default.";
			logger.warn(str);
		}
		Map<String, Object> contentParams = new HashMap<String, Object>();
		contentParams.put("contentId", contentId);
		contentParams.put("language", refTableDetail.getData1Value());
		ContentText contentText = this.contentTextService.findUniqueByParams(contentParams);
		if (contentText == null) {
			return fieldVO;
		}
		fieldVO.setContentText(contentText.getContentText());
		return fieldVO;
	}

	/**
	 * 根据refTableId查询返回对应的数据列表
	 * @param refTableId
	 * @return List
	 * @author xuzhang4
	 * @since  2008-7-27
	 */
	public List<RefTableDetail> findRefValueList(String refTableId) {
		if (StringUtils.isEmpty(refTableId)) {
			String str = "Illegal empty refTableId.";
			logger.warn(str);
			throw new IllegalArgumentException(str);
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("refTableId", refTableId);
		return this.refTableDetailService.findByParams(params);
	}

	/**
	 * 根据refTableId, key1Value, key2Value查询返回对应的数据
	 * @param refTableId
	 * @return RefTableDetail
	 * @author xuzhang4
	 * @since  2008-7-29
	 */
	public RefTableDetail findRefValue(String refTableId, String key1Value, String key2Value) {
		if (StringUtils.isEmpty(refTableId)) {
			String str = "Illegal empty refTableId.";
			logger.warn(str);
			throw new IllegalArgumentException(str);
		}
		if (StringUtils.isEmpty(key1Value)) {
			String str = "Illegal empty key1Value.";
			logger.warn(str);
			throw new IllegalArgumentException(str);
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("refTableId", refTableId);
		params.put("key1Value", key1Value);
		params.put("key2Value", key2Value);
		return this.refTableDetailService.findUniqueByParams(params);
	}
	/**
	 * 根据refTableId，默认取RefTableDetail对象的key1和data1作为Map的key-value
	 * 主要用于下拉框数据显示及列表数据转义显示
	 * @param refTableId
	 * @return Map
	 * @author xuzhang4
	 * @since  2008-7-27
	 */
	public Map<String, String> findRefValueMap(String refTableId) {
		if (StringUtils.isEmpty(refTableId)) {
			String str = "Illegal empty refTableId.";
			logger.warn(str);
			throw new IllegalArgumentException(str);
		}
		List<RefTableDetail> list =  findRefValueList(refTableId);
		if (list == null) {
			return null;
		}
		Map<String, String> result = new LinkedHashMap<String, String>();
		for (RefTableDetail detail : list) {
			result.put(detail.getKey1Value(), detail.getData1Value());
		}
		return result;
	}

	public RefTableDetailService getRefTableDetailService() {
		return refTableDetailService;
	}

	public void setRefTableDetailService(RefTableDetailService refTableDetailService) {
		this.refTableDetailService = refTableDetailService;
	}

	public FieldDefinitionService getFieldDefinitionService() {
		return fieldDefinitionService;
	}

	public void setFieldDefinitionService(
			FieldDefinitionService fieldDefinitionService) {
		this.fieldDefinitionService = fieldDefinitionService;
	}

	public ContentTextService getContentTextService() {
		return contentTextService;
	}

	public void setContentTextService(ContentTextService contentTextService) {
		this.contentTextService = contentTextService;
	}
}
